using AdminApiTemplate.Common.Exceptions;
using AdminApiTemplate.Common.Helpers;
using System.Text;
using System.Text.RegularExpressions;

namespace AdminApiTemplate.Test
{
    public class Sql2Model
    {
        public static void Build(string input)
        {
            var parts = input.Split(',');
            var connStr = parts[0].ToLower();

            var database_init = "";
            var dbType = default(DBTypeEnum?);
            if (connStr.Contains("data source"))
            {
                dbType = DBTypeEnum.SqlServer;
                database_init = GetConnectionStringPart(connStr, "catalog", ";");
                database_init = database_init.Replace("=", "").Trim();
            }

            if (connStr.Contains("datasource") && connStr.Contains("userid"))
            {
                dbType = DBTypeEnum.MySql;
                database_init = GetConnectionStringPart(connStr, "database", ";");
                database_init = database_init.Replace("=", "").Trim();
            }

            if (!dbType.HasValue || string.IsNullOrEmpty(database_init))
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "连接字符串无效");
            }

            var dbName = default(string);
            if (parts.Length > 1)
            {
                dbName = parts[1];
            }

            var tableName = default(string);
            if (parts.Length > 2)
            {
                tableName = parts[2];
            }

            var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), $"Models{RandomHelper.RequestId()}");
            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            string sql;
            if (dbType == DBTypeEnum.SqlServer)
            {
                sql = "SELECT [Id],[Name] FROM [SYSOBJECTS] WHERE TYPE='U'";
                var tables = new MySqlHelper(connStr).GetList<TableItem>(sql);
                foreach (var table in tables)
                {
                    var fileName = $"{table.Name}.cs";
                    var fullName = Path.Combine(folder, fileName);

                    var sb = new StringBuilder();
                    sb.AppendLine($"[Description(\"\")]");
                    sb.AppendLine($"[Table(\"{table.Name}\")]");
                    sb.AppendLine($"public class {table.Name}");
                    sb.AppendLine("{");
                    sql=$"select [name],[type] [DataType],[isnullable] [IsNull] from [syscolumns] where id = {table.Id.GetValueOrDefault()} ";
                    var columns = new MySqlHelper(connStr).GetList<ColumnItem>(sql);
                    for (var i = 0; i<columns.Count; i++)
                    {
                        var column = columns[i];
                        if (i>0)
                        {
                            sb.AppendLine();
                        }

                        string type;
                        switch (column.DataType)
                        {
                            default:
                                {
                                    type = "object";
                                    break;
                                }
                            case "61":
                            case "111":
                                {
                                    type = "DateTime?";
                                    break;
                                }
                            case "50":
                                {
                                    type = "bool?";
                                    break;
                                }
                            case "38":
                            case "56":
                                {
                                    type = "int?";
                                    break;
                                }
                            case "63":
                                {
                                    type = "long?";
                                    break;
                                }
                            case "60":
                            case "106":
                            case "110":
                                {
                                    type = "decimal?";
                                    break;
                                }
                            case "39":
                                {
                                    type = "string";
                                    break;
                                }
                        }
                        sb.AppendLine("        /// <summary>");
                        sb.AppendLine($"        /// {column.Remark}");
                        sb.AppendLine("        /// </summary>");
                        if (column.IsNull=="0")
                        {
                            sb.AppendLine("        [Required(ErrorMessage =\"必填\")]");
                        }
                        if (column.DataType=="string")
                        {
                            sb.AppendLine("        [MaxLength("+column.MaxLength+",ErrorMessage =\"最多{0}个字符\")]");
                        }
                        sb.AppendLine($"        [Description(\"{column.Remark}\")]");
                        sb.AppendLine("        public "+type+" "+column.Name+" { get; set; }");
                    }
                    sb.AppendLine("}");
                    var content = sb.ToString();
                    File.WriteAllText(fullName, content, Encoding.UTF8);
                }
            }

            if (dbType == DBTypeEnum.MySql)
            {
                sql="SELECT TABLE_NAME `Name` from information_schema.`TABLES` t1 WHERE t1.TABLE_SCHEMA=@database_init";
                var tables = new MySqlHelper(connStr).GetList<TableItem>(sql, new { database_init });
                foreach (var table in tables)
                {
                    var fileName = $"{table.Name}.cs";
                    var fullName = Path.Combine(folder, fileName);

                    var sb = new StringBuilder();
                    sb.AppendLine("using System.ComponentModel;");
                    sb.AppendLine("using System.ComponentModel.DataAnnotations;");
                    sb.AppendLine("using System.ComponentModel.DataAnnotations.Schema;");
                    sb.AppendLine();
                    sb.AppendLine("namespace AdminApiTemplate.Infrastructures.Domains");
                    sb.AppendLine("{");
                    sb.AppendLine("    /// <summary>");
                    sb.AppendLine($"    /// ");
                    sb.AppendLine("    /// </summary>");
                    sb.AppendLine($"    [Description(\"\")]");
                    sb.AppendLine($"    [Table(\"{table.Name}\")]");
                    sb.AppendLine($"    public class {table.Name}");
                    sb.AppendLine("    {");
                    sql="SELECT t1.COLUMN_NAME `Name`,t1.COLUMN_COMMENT `Remark`,t1.DATA_TYPE `DataType`,t1.CHARACTER_MAXIMUM_LENGTH `MaxLength`,t1.IS_NULLABLE `IsNull` FROM information_schema.`COLUMNS` t1 WHERE t1.TABLE_SCHEMA=@database_init and t1.TABLE_NAME=@table_name";
                    var columns = new MySqlHelper(connStr).GetList<ColumnItem>(sql, new { database_init, table_name = table.Name });
                    for (var i = 0; i<columns.Count; i++)
                    {
                        var column = columns[i];
                        if (i>0)
                        {
                            sb.AppendLine();
                        }

                        string type;
                        switch (column.DataType)
                        {
                            default:
                                {
                                    type = "object";
                                    break;
                                }
                            case "datetime":
                                {
                                    type = "DateTime?";
                                    break;
                                }
                            case "bit":
                                {
                                    type = "bool?";
                                    break;
                                }
                            case "int":
                                {
                                    type = "int?";
                                    break;
                                }
                            case "bigint":
                                {
                                    type = "long?";
                                    break;
                                }
                            case "decimal":
                                {
                                    type = "decimal?";
                                    break;
                                }
                            case "varchar":
                                {
                                    type = "string";
                                    break;
                                }
                        }
                        sb.AppendLine("        /// <summary>");
                        sb.AppendLine($"        /// {column.Remark}");
                        sb.AppendLine("        /// </summary>");
                        if (column.IsNull=="NO")
                        {
                            sb.AppendLine("        [Required(ErrorMessage =\"必填\")]");
                        }
                        if (column.DataType=="string")
                        {
                            sb.AppendLine("        [MaxLength("+column.MaxLength+",ErrorMessage =\"最多{0}个字符\")]");
                        }
                        sb.AppendLine($"        [Description(\"{column.Remark}\")]");
                        sb.AppendLine("        public "+type+" "+column.Name+" { get; set; }");
                    }
                    sb.AppendLine("    }");
                    sb.AppendLine("}");
                    var content = sb.ToString();
                    File.WriteAllText(fullName, content, Encoding.UTF8);
                }
            }
        }

        private static string GetConnectionStringPart(string connStr, string start, string end)
        {
            var idx = connStr.IndexOf(start);
            if (idx>=0)
            {
                var part = connStr.Substring(idx+start.Length);
                var idx2 = part.IndexOf(end);
                if (idx2>=0)
                {
                    var part2 = part.Substring(0, idx2);
                    return part2;
                }
            }

            return null;
        }
    }

    public class TableItem
    {
        public long? Id { get; set; }

        public string Name { get; set; }
    }

    public class ColumnItem
    {
        public string Name { get; set; }

        public string Remark { get; set; }

        public string DataType { get; set; }

        public string MaxLength { get; set; }

        public string IsNull { get; set; }
    }
}
